<?php
namespace control;
/*
*销项发票类
*/

class saleInvoiceClass extends adIndexClass
{
    private const page = 'saleInvoice';
    private const table = 'invoice_open';
    private const table_mx = 'invoice_open_detail';
    private static string $title;
    public array $stateOption;
    public array $sourceOption;

    public function __construct()
    {
        parent::__construct();
        self::$title  = L('销项发票');
        $this->stateOption    = [L('未开'), L('正数正常'), L('负数正常'), L('作废')];
        $this->sourceOption    = [L('手填发票'), L('销售发货'), L('采购收货')];
    }

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            case 'businessInvoiceSearch':
                $tr = [
                    'stid'          => [
                        'name'  => L('申请人'),
                        'width' => 120,
                    ],
                    'classify'  => [
                        'name'  => L('发票性质'),
                        'width' => 100,
                    ],
                    'buyCompany'          => [
                        'name'  => L('客户名称'),
                        'width' => 200,
                    ],
                    'money'          => [
                        'name'  => L('价税合计').'（' . static::$unit . '）',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'invoiceCode'          => [
                        'name'  => L('发票代码'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'invoiceNo'          => [
                        'name'  => L('发票号码'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'invoiceDate'          => [
                        'name'  => L('开票日期'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'state'         => [
                        'name'  => L('发票状态'),
                        'width' => 100,
                    ],
                    'text'          => [
                        'name'  => L('备注'),
                        'width' => 120,
                    ]
                ];
                break;
            default:
                $tr = [
                    'invoiceDate'          => [
                        'name'  => L('开票日期'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'classify'  => [
                        'name'  => L('发票性质'),
                        'width' => 100,
                    ],
                    'state'         => [
                        'name'  => L('发票状态'),
                        'width' => 100,
                    ],
                    'source'          => [
                        'name'  => L('发票来源'),
                        'width' => 120,
                    ],
                    'invoiceCode'          => [
                        'name'  => L('发票代码'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'invoiceNo'          => [
                        'name'  => L('发票号码'),
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'buyCompany'          => [
                        'name'  => L('购货单位'),
                        'width' => 200,
                    ],
                    'saleCompany'          => [
                        'name'  => L('销货单位'),
                        'width' => 200,
                    ],
                    'money'          => [
                        'name'  => L('价税合计').'（' . static::$unit . '）',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'unTaxMoney'          => [
                        'name'  => L('未税金额').'（' . static::$unit . '）',
                        'width' => 150,
                        'sort' => 1,
                    ],
                    'taxMoney'          => [
                        'name'  => L('税额').'（' . static::$unit . '）',
                        'width' => 120,
                        'sort' => 1,
                    ],
                    'text'          => [
                        'name'  => L('备注'),
                        'width' => 120,
                    ]
                ];
        }
        return $tr;
    }

    /*列表页-查询条件*/
    public function clientInvoiceOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('状态') => checkbox(array('name' => 'state', 'maintain_index' => true, 'value' => $this->stateOption, 'checked' => [0,1,2])),
                ],
                [
                    L('发票性质') => select(array("name" => "invoiceType", "title" => L('发票性质'), 'option' => ['普票', '专票'])),
                    L('发票代码')   => text(array("name" => "invoiceCode")),
                    L('发票号码')   => text(array("name" => "invoiceNo")).
                        hidden(array("name" => "targetId", "value" => $this->get('id')?$this->get('id'):$this->post('id'))),
                ],
                [
                    L('销货单位')   => text(array("name" => "saleCompany")),
                    L('备注')   => text(array("name" => "text")),
                    L('开票日期') => text(array("name" => "createTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /**
     * 客户页卡
     *
     * @return bool|string
     */
    public function clientInvoice(): bool|string
    {
        $html = $this->clientInvoiceOptions(false);
        $button = "";
        //返回
        $json['html'] = $this->search($html, layout: 'pop', toolButton: $button, searchOption: "{id:'".$this->get('id')."'}");
        return json_encode($json, 320);
    }

    public function clientInvoiceSearch(): bool|string
    {
        $khid = $this->post('targetId');
        //like查询数组
        $like = array(
            //编号
            "text" => $this->post('text'),//事由
            "buyCompany" => $this->post('buyCompany'),
            "saleCompany" => $this->post('saleCompany'),
            "invoiceNo" => $this->post('invoiceNo'),
            "invoiceCode" => $this->post('invoiceCode'),
        );
        //全等查询数组
        $equal = array(
            "classify" => $this->post('invoiceType'),
            "type" => '开票',
            'coid' => self::$coid
        );
        //in查询数组
        $in = array(
            "state" => $this->post('state'),
        );
        $and = $this->seeSelf(self::page)." and khid = '$khid'";
        if ($this->post('createTime')) {
            $and.=self::timeComparison($this->post('createTime'),field: 'invoiceDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'invoiceDate',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal, "in" => $in)) . $and;
        $page = $this->page(array("table" => self::table, "where" => $where, "order" => $orderBy['orderBy']));
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array("");
        //获取记录
        $url = root . "control/adIndex.html?cla=openInvoice";
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                //"detail" => array("title" => L('销项发票详情'), "click" => "newIframe('" . L('销项发票详情'). "','" . $url . "&fun=home&id=" . $array['id'] . "')"),
                "detail" => array("title" => L('查看发票'), "click" => "layer('".self::page."','invoicing',{id:'" . $array['id'] . "', type:'see'})"),
            );
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'state':
                        $row[] = $this->stateOption[$array['state']];
                        break;
                    case 'source':
                        $row[] = $this->sourceOption[$array['source']];
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = $page['hint']  . "<form name='listForm'>" . $li . "</form>" . $page['button'] . clear;
        return json_encode($json, 320);
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('状态') => checkbox(array('name' => 'state', 'maintain_index' => true, 'value' => $this->stateOption, 'checked' => [0,1,2])),
                ],
                [
                    L('发票性质') => select(array("name" => "invoiceType", 'option' => ['普票', '专票'])),
                    L('发票代码')   => text(array("name" => "invoiceCode")),
                    L('发票号码') => text(array("name" => "invoiceNo")),
                ],
                [
                    L('购货单位') => text(array("name" => "buyCompany")),
                    L('销货单位') => text(array("name" => "saleCompany")),
                    L('备注') => text(array("name" => "text")),
                ],
                [
                    L('开票日期') => text(array("name" => "createTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }


    /*列表-查询条件*/
    public function home()
    {
        $html = $this->homeOptions(false);
        //控件
        $button = "";
        $url = root . "control/adIndex.html?cla=openInvoice";
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"newIframe('".L('开票')."','" . $url . "&fun=home')\" class='spanButton'>" . L('手填发票'). "</span>\n";
            $button .= "<span onclick=\"layer('".self::page."','invoiceApply')\" class='spanButton'>" . L('业务发票'). "</span>\n";
        }

        if ($this->power(self::page, "del")) {
            $button .= "<span class='spanButton' onclick=\"layer('{$this->get('cla')}', 'operate', {'act': 'del'})\">" . L('删除'). "</span>\n";
        }
        if ($this->power(self::page, 'import')) {
            $button .="<span class='spanButton' onclick=\"layer('importTemplate','importFrame',{cla:'".self::page."'})\">" . L('导入'). "</span>";
        }
        if ($this->power(self::page, "export")) {
            $button .= "  <a href='" . root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=exportData'><span class='spanButton'>" . L('导出'). "</span></a>\n";
        }
        if ($this->power(self::page, "edit")) {
            $button .= "<span onclick=\"layer('{$this->get('cla')}','stateSwitch',{state:3})\" class='spanButton'>" . L('作废'). "</span>\n";
        }
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /*客户列表-查询结果*/
    public function homeSearch()
    {
        //like查询数组
        $like = array(
            //编号
            "text" => $this->post('text'),//事由
            "buyCompany" => $this->post('buyCompany'),
            "saleCompany" => $this->post('saleCompany'),
            "invoiceNo" => $this->post('invoiceNo'),
            "invoiceCode" => $this->post('invoiceCode'),
        );
        //全等查询数组
        $equal = array(
            "classify" => $this->post('invoiceType'),
            "type" => '开票',
            'coid' => self::$coid
        );
        //in查询数组
        $in = array(
            "state" => $this->post('state'),
        );
        $and = $this->seeSelf(self::page);
        if ($this->post('createTime')) {
            $and.=self::timeComparison($this->post('createTime'),field: 'invoiceDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'time desc,invoiceDate',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal, "in" => $in)) . $and;
        $page = $this->page(array("table" => self::table, "where" => $where, "order" => $orderBy['orderBy']));
        $_SESSION[self::page]['sql'] = $page['fullSql'];
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        //获取记录
        $url = root . "control/adIndex.html?cla=openInvoice";
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                "box" => array("name" => "listId", "value" => $array['id']),
                "detail" => array("title" => L('查看发票'), "click" => "layer('".self::page."','invoicing',{id:'" . $array['id'] . "', type:'see'})"),
            );
            if($array['state'] == 0){
                $dominate['invoicing'] = array("title" => L('发票填开'), "click" => "layer('".self::page."','invoicing',{id:'" . $array['id'] . "', type:'fill'})");
            }elseif($array['state'] == 1 && self::total(['table'=>'invoice_open','where'=>"coid = '".self::$coid."' and red_target = '" . $array['id'] . "'"]) == 0){
                $dominate['invoice_red'] = array("title" => L('发票冲红'), "click" => "layer('".self::page."','invoicing',{id:'" . $array['id'] . "', type:'red'})");
                $dominate['invoice_cancel'] = array("title" => L('发票作废'), "click" => "layer('{$this->get('cla')}','stateSwitch',{state:3, id:'" . $array['id'] . "'})");
            }

            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'state':
                        $row[] = $array['state'] == 2 ? "<span class='red'>".$this->stateOption[$array['state']]."</span>" : $this->stateOption[$array['state']];
                        break;
                    case 'source':
                        $row[] = $this->sourceOption[$array['source']];
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = $page['hint'] . "<form name='listForm'>" . $li . "</form>" . $page['button'] . clear;
        return json_encode($json, 320);
    }


    /**
     * 启修改状态
     */
    public function stateSwitch()
    {
        $state = $this->post('state');
        $typeText = $this->stateOption[$state];
        //生成表单
        $html = $this->layerEdit(array(
            "table" => array(
                array(
                    L('提示')."：" =>  L('是否修改所选数据状态为') . "：" . $typeText,
                ),
            ),
            'hidden' => hidden(array('name' => 'state', 'value' => $state)).
                hidden(array('name' => 'id', 'value' => $this->post('id')))
        ));
        //返回
        return $this->layer(array("title" => L('状态切换'), "height" => 165, "html" => $html, 'formTwo' => 'listForm'));
    }

    /**
     * 修改状态
     */
    public function stateSwitchEdit()
    {
        $idArr = $this->post('id') ? [$this->post('id')] : $this->post('listId');
        $state = $this->post('state');
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = L('您还没有销项发票的编辑权限');
        } elseif (empty($idArr) || !is_array($idArr)) {
            $json['warn'] = L('请选择数据');
        } elseif (!in_array($state, [3])) { //目前仅支持作废操作
            $json['warn'] = L('状态错误');
        } else {
            // 更新销售发货单已开票数量
            $text = "";
            $x = 0;
            foreach ($idArr as $id) {
                $where = " id = '$id' ";
                $info  = query('invoice_open', $where);
                // 只有正数正常才能作废
                if($info['state'] != 1) {
                    $text .= str_replace(['{{invoiceNo}}','{{id}}'],[$info['invoiceNo'],$info['id']],L('销项发票【{{invoiceNo}}】-【{{id}}】')) . L('作废失败，只有正数正常才能作废') . "。<br>";
                }else{
                    $field = [
                        'state' => $state,
                    ];
                    $json['warn'] = update(array('table' => self::table, 'field' => $field, 'where' => $where));
                    if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                        $result = find(['table' => 'invoice_open_detail', 'where' => "orderId = '$info[id]' and sourceId <> '' order by list"]);
                        foreach ($result['array'] as $k => $array) {
                            $sale_send_order_detail = query("sale_send_order_detail", " id = '$array[sourceId]' ");
                            if ($sale_send_order_detail['id']) {
                                // 正数正常作废，则扣减已开票数量
                                update(array(
                                    'table' => "sale_send_order_detail",
                                    'field' => [
                                        'invoice_num' => $sale_send_order_detail['invoice_num'] - $array['num'],
                                    ],
                                    'where' => "id = '" . $sale_send_order_detail['id'] . "'"
                                ));
                            }
                        }
                        $x++;
                        $text .= str_replace(['{{invoiceNo}}','{{id}}'],[$info['invoiceNo'],$info['id']],L('销项发票【{{invoiceNo}}】-【{{id}}】')) . L('已作废') . "。<br>";
                    }
                }

            }
            //添加日志
            $text =str_replace(['{{staffName}}'],[$this->control['name']],L('{{staffName}}作废了销项发票，结果如下：'))   . "<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] =str_replace(['{{x}}'],[$x],L('作废了{{x}}个销项发票，详情请查看系统日志')) ;
            $json['warn'] = 2;
        }
        //返回
        return json_encode($json, 320);
    }
    // 操作中转
    public function operate()
    {
        $act = $this->post('act') ?? '';
        $pwd = false; // 需要密码
        switch ($act) {
            default:
                $act = 'del';
                $msg = L('删除销项发票');
                $title = self::page . 'Delete';
                $function = 'delete';
                $form = self::page . 'OperateForm, listForm';
                $power = '';
                break;
        }
        if (!$this->power(self::page, $act)) {
            $_SESSION['warn'] = str_replace(['{{msg}}'], [$msg], L('你还没有{{msg}}的权限'));
            $json = [
                'warn' => 2,
                'href' => root . 'control/adIndex.html?cla=' . $this->get('cla') . '&fun=home',
            ];
        } else {
            return $this->confirm([
                'title' => $title,
                'function' => $function,
                'form' => $form,
                'power' => $power,
                'pwd' => $pwd,
            ]);
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 删除
     * @return bool|string
     */
    public function delete()
    {
        $array = $this->post('listId') ?? $this->post('id');
        if (!$this->power(self::page, "del")) {
            $json['warn'] = L('你没有删除的权限');
        } elseif (empty($array)) {
            $json['warn'] = L('你一个数据都没有选择呢');
        } else {
            $text = "";
            $x = 0;
            $array = is_array($array) ? $array : [$array];
            foreach ($array as $id) {
                $info = query(self::table, " id = '$id' ");
                if($info['state'] != 0 && $info['state'] != 3){
                    $text .= str_replace(['{{invoiceNo}}','{{id}}'],[$info['invoiceNo'],$info['id']],L('销项发票【{{invoiceNo}}】-【{{id}}】')) . L('只有作废和未开发票可删除') . "。<br>";
                }else{
                    //最后删除基本参数
                    delete(array("table" => self::table, "where" => " id = '$id' "));
                    delete(array("table" => self::table_mx, "where" => " orderId = '$id' "));
                    //返回
                    $warn = L('删除成功');
                    $x++;
                    $text .= str_replace(['{{invoiceNo}}','{{id}}'],[$info['invoiceNo'],$info['id']],L('销项发票【{{invoiceNo}}】-【{{id}}】')) . $warn . "。<br>";
                }
            }
            //添加日志
            $text =str_replace(['{{staffName}}'],[$this->control['name']],L('{{staffName}}删除了销项发票，结果如下：'))   . "<br>" . $text;
            $this->logText(array("type" => self::page, "text" => $text));
            $_SESSION['warn'] =str_replace(['{{x}}'],[$x],L('删除了{{x}}个销项发票，详情请查看系统日志')) ;
            $json['warn'] = 2;
            $json['href'] = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=home";
        }
        return json_encode($json, 320);
    }

    /**
     * 导出
     */
    public function exportData()
    {
        if (!$this->power(self::page, 'export')) {
            $_SESSION['warn'] = L('你还没有导出的权限');
        } else {
            $data = [];
            $sql = $_SESSION[self::page]['sql'];
            $title = [L('发票代码'), L('发票编号'), L('发票日期'), L('发票类型'), L('是否含税(是/否)'), L('购货单位名称'), L('购货纳税人识别号'), L('finance.table.ghdz、dh'), L('购货开户行及账号'), L('销货单位名称'), L('销货纳税人识别号'), L('finance.table.xhdz、dh'), L('销货开户行及账号'),
                L('收款人'), L('复核人'), L('开票人'), L('合计'), L('税额'), L('价税合计'), L('备注'), L('货物或应收劳务名称'), L('规格型号'), L('单位'), L('数量'), L('单价'), L('金额'), L('税率'), L('税额')];
            $result = self::sqlFind($sql);
            if (is_array($result)) {
                foreach ($result as $array) {
                    $all = find(array('table' => 'invoice_open_detail', 'where' => "orderId = '$array[id]' order by list asc"));
                    foreach ($all['array'] as $item) {
                        $data[] = [$array['invoiceCode'], $array['invoiceNo'], $array['invoiceDate'], $array['classify'], $array['isTax'] ? '是' : '否', $array['buyCompany'],
                            $array['buyTaxNo'], $array['buyAddress'], $array['buyBank'], $array['saleCompany'],
                            $array['saleTaxNo'], $array['saleAddress'], $array['saleBank'], $array['receiveName'], $array['checkName'],
                            $array['createName'], $array['unTaxMoney'], $array['taxMoney'], $array['money'], $array['text'], $item['name'],
                            $item['model'], $item['unit'], $item['num'], currencyClass::intToDecimal($item['price'], $item['baseUnit']),
                            $item['money'], $item['tax'] * 100, $item['taxMoney']];
                    }
                }
            }
            $text = str_replace(['{{staffName}}'],[$this->control['name']],L('{{staffName}}导出了销项发票'));
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOut($title, $data, L('销项发票').".xlsx");
        }
        header("Location:" . getenv("HTTP_REFERER"));
        exit(0);
    }

    /**
     * 下载模板
     */
    public function downloadModel()
    {
        $templateId = $this->get('templateId');
        if (!$this->power(self::page, 'import')) {
            $_SESSION['warn'] = "您还没有导入的权限";
        } else {
            $exampleData = [];
            $excel    = $this->excelHead();
            $fileName = self::$title.'导入模板-'.importTemplateClass::getName($templateId).'.xlsx';
            $filePath = $excel->fileName($fileName, 'sheet1');
            $format = new \Vtiful\Kernel\Format($filePath->getHandle());
            $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
            $index         = 0;
            foreach ($templateField as $k => $array) {
                if ($array['display']){
                    $backgroundStyle=null;
                    if (importTemplateClass::getIsMustValue($this->importFieldInit(), $array['columnName'])){
                        //必填项判断
                        $backgroundStyle  = $format->background(
                            0xFFC04B
                        )->toResource();
                    }
                    $filePath->insertText(0, $index, $array['aliasName'],null,$backgroundStyle);
                    foreach ($exampleData as $y=>$example){
                        $exampleVal = match ($array['columnName']){
                            '发票代码'=>$example[0],
                            '发票编号'=>$example[1],
                            '发票日期'=>$example[2],
                            '发票类型'=>$example[3],
                            '是否含税'=>$example[4],
                            '购货单位名称'=>$example[5],
                            '购货纳税人识别号'=>$example[6],
                            '购货地址、电话'=>$example[7],
                            '购货开户行及账号'=>$example[8],
                            '销货单位名称'=>$example[9],
                            '销货纳税人识别号'=>$example[10],
                            '销货地址、电话'=>$example[11],
                            '销货开户行及账号'=>$example[12],
                            '收款人'=>$example[13],
                            '复核人'=>$example[14],
                            '开票人'=>$example[15],
                            '合计'=>$example[16],
                            '税额合计'=>$example[17],
                            '价税合计'=>$example[18],
                            '备注'=>$example[19],
                            '货物或应收劳务名称'=>$example[20],
                            '规格型号'=>$example[21],
                            '单位'=>$example[22],
                            '数量'=>$example[23],
                            '单价'=>$example[24],
                            '金额'=>$example[25],
                            '税率'=>$example[26],
                            '税额'=>$example[27],
                            default=>'',
                        };
                        $filePath->insertText($y+1, $index, $exampleVal);
                    }
                    $index++;
                }
            }
            $text = str_replace(['{{staffName}}'],[$this->control['name']],L('{{staffName}}下载了发票导入模板'));
            $this->logText(["type" => self::page, "text" => $text]);
            $this->excelOutPut($filePath,$fileName);
            exit(0);
        }
        header("Location:" . getenv("HTTP_REFERER"));
    }

    /*数据导入分析*/
    public function importData()
    {
        $templateId = $this->post('templateId');
        if (!$this->power(self::page, 'import')) {
            $json['warn'] = L('你还没有导入的权限');
        }  else {
            $fomatArray = [];//导入数据格式同一为TYPE_STRING
            foreach ($this->importFieldInit() as $value){
                $fomatArray[] = \Vtiful\Kernel\Excel::TYPE_STRING;
            }
            $data = $this->importHead(format: $fomatArray);
            $x = $i = 0;
            $text = '';
            $preInvoice = [];
            $this->startTrans();
            $headArray = [];
            $row_list=0;
            foreach ($data as $i => $row) {
                $row_list++;
                if ($i==0){
                    $templateField = importTemplateClass::templateField(self::page, 'importFieldInit', id:$templateId);
                    $headArray = importTemplateClass::combinHead($templateField,$row);
                }
                if ($i > 0) {
                    $line = str_replace(['{{i}}'], [$row_list], L('第【{{i}}】行'));
                    $rowData = formSubArray($row);
                    //只接收模板中选中的字段的值
                    $cell = [];
                    foreach ($headArray as $index=>$headName){
                        $cell[$headName] = $rowData[$index]??'';
                    }
                    //初始化未被模板需要的字段的值
                    foreach ($this->importFieldInit() as $value){
                        $cell[$value['columnName']] = $cell[$value['columnName']]??'';
                    }
                    //主表
                    $invoice = query('invoice_open', "coid = '" . self::$coid . "' and invoiceCode = '$cell[发票代码]'");
                    if (empty($preInvoice) || $preInvoice['invoiceCode'] != $cell['发票编号']) {
                        if (isset($preInvoice['id']) && !empty($preInvoice['id'])) {
                            $total = find(array('table' => 'invoice_open_detail', 'single' => "orderId = '$preInvoice[id]'", 'field' => "ifnull(sum(taxMoney),0) as taxMoney,ifnull(sum(money),0) as money"));
                            $taxMoney = $total['taxMoney'];
                            //统计价税合计和税额
                            if ($preInvoice['isTax']) {
                                $withTaxMoney = $total['money'];
                            } else {
                                $withTaxMoney = $total['money'] + $taxMoney;
                            }
                            update(array('table' => 'invoice_open', 'field' => ['taxMoney' => $taxMoney, 'money' => $withTaxMoney, 'unTaxMoney' => $withTaxMoney - $taxMoney], 'where' => "id = '$preInvoice[id]'"));
                        }
                        $preInvoice = [];
                        $field = [
                            'id' => suiji(),
                            'stid' => self::$stid,
                            'state' => '正常',
                            'type'=>'开票',
                            'coid' => self::$coid,
                            'classify' => $cell['发票类型'] ?: '普票',
                            'buyCompany' => $cell['购货单位名称'],
                            'buyTaxNo' => $cell['购货纳税人识别号'],
                            'buyAddress' => $cell['购货地址、电话'],
                            'buyBank' => $cell['购货开户行及账号'],
                            'checkName' => $cell['复核人'],
                            'receiveName' => $cell['收款人'],
                            'createName' => $cell['开票人'],
                            'invoiceDate' => $cell['发票日期'],
                            'invoiceCode' => $cell['发票代码'],
                            'invoiceNo' => $cell['发票编号'],
                            'isTax' => $cell['是否含税'] == '是' ? 1 : 0,
                            'saleCompany' => $cell['销货单位名称'],
                            'saleTaxNo' => $cell['销货纳税人识别号'],
                            'saleAddress' => $cell['销货地址、电话'],
                            'saleBank' => $cell['销货开户行及账号'],
                            'text' => $cell['备注'],
                        ];

                        $annotation = [
                            'invoiceDate' => L('开票日期'),
                            'invoiceCode' => L('发票代码'),
                            'invoiceNo' => L('发票编号'),
                            'buyCompany' => L('购货单位名称'),
                            'buyTaxNo' => L('购货单位纳税人识别号'),
                            'saleCompany' => L('销货单位'),
                            'saleTaxNo' => L('销货单位纳税人识别号'),
                        ];
                        $rules = [
                            'invoiceDate' => 'required',
                            'invoiceCode' => 'required',
                            'invoiceNo' => 'required',
                            'buyCompany' => 'required',
                            'buyTaxNo' => 'required',
                            'saleCompany' => 'required',
                            'saleTaxNo' => 'required',
                        ];

                        // 校验是否符合规则
                        $vt = new \verify();
                        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
                        if ($result === false) {
                            $text .= $line."：" . $vt->getErrs()[0] . "<br>";  // 多个规则提示最前面一条
                        } elseif (static::total(array('table' => self::table, 'where' => "coid = '" . self::$coid . "' and type = '开票' and invoiceCode = '$field[invoiceCode]'")) > 0) {
                            $text .= $line."：".L('已存在此发票')."<br>";
                        } else {
                            $warn = insert(["table" => self::table, "field" => $field]);
                            if (in_array($warn, ["新增成功", "更新成功"])) {
                                $preInvoice = $field;
                                $text .= $line."：".L('导入成功')."<br>";
                            } else {
                                $text .= $line."：".L('导入失败：编辑失败')."<br>";
                            }
                        }
                    }

                    if (isset($preInvoice['id']) && !empty($preInvoice['id'])) {
                        //明细
                        if (!empty($cell['货物或应收劳务名称'])) {
                            $text .= $line."：".L('未找到货物或应收劳务名称')."<br>";
                        } elseif (empty($cell['金额']) || preg_match(checkPrice, $cell['金额']) == 0) {
                            $text .= $line."：".L('未填写金额')."<br>";
                        } else {
                            $baseUnit = currencyClass::calculateDecimal($cell['单价']);
                            $warn = static::insert(array(
                                'table' => 'invoice_open_detail',
                                'field' => [
                                    'id' => suiji(),
                                    'coid' => self::$coid,
                                    'orderId' => $preInvoice['id'],
                                    'name' => $cell['货物或应收劳务名称'],
                                    'model' => $cell['规格型号'],
                                    'unit' => $cell['单位'],
                                    'price' => $cell['单价'] * $baseUnit,
                                    'baseUnit' => $baseUnit,
                                    'num' => $cell['数量'],
                                    'money' => $cell['金额'],
                                    'tax' => $cell['税率'] / 100,
                                    'taxMoney' => $cell['税额'],
                                ],
                            ));
                            if ($warn == '新增成功') {
                                $x++;
                                $text .= $line."：".L('发票明细导入成功')."<br>";
                            } else {
                                $text .= $line."：".L('发票明细导入失败')."<br>";
                            }
                        }
                    }
                    $preInvoice = $invoice;
                }
            }
            if ($i == $x && $x > 0) {
                $this->commitTrans();
            } else {
                $this->rollback();
            }
            $total = count($data)-1;
            $json['data'] = [
                'text'=>$text,
                'title'=>"您导入了{$total}条数据，成功{$x}条，失败".($total-$x)."条",
            ];
            $text =str_replace(['{{staffName}}','{{fileName}}'],[$this->control['name'],$_FILES['file']['name']],L('{{staffName}}导入了文件：{{fileName}}'))  .  '：' . $text;
            $this->logText(["type" => self::page, "text" => $text]);
            $json['warn'] = 2;
        }
        return json_encode($json,320);
    }

    /**
     * 导入模板字段初始化
     * @return array[]
     */
    public function importFieldInit($classify=''): array
    {
        return match ($classify) {
            default=>  [
                [
                    'columnName'=>'发票代码',
                    'isMust'=>true,
                    'isRepeat'=>true,
                ],
                [
                    'columnName'=>'发票编号',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'发票日期',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'发票类型',
                    'aliasName'=>'发票类型(普票/专票)',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'是否含税',
                    'aliasName'=>'是否含税(是/否)',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'购货单位名称',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'购货纳税人识别号',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'购货地址、电话',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'购货开户行及账号',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'销货单位名称',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'销货纳税人识别号',
                    'isMust'=>true,
                ],
                [
                    'columnName'=>'销货地址、电话',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'销货开户行及账号',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'收款人',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'复核人',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'开票人',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'合计',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'税额合计',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'价税合计',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'备注',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'货物或应收劳务名称',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'规格型号',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'单位',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'数量',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'单价',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'金额',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'税率',
                    'aliasName'=>'税率%',
                    'isMust'=>false,
                ],
                [
                    'columnName'=>'税额',
                    'isMust'=>false,
                ],
            ]
        };
    }

    /**
     * Desc : 开票编辑页详情页表格行
     * User : you name
     * Date : 2025-01-06 14:11
     * @param array $params $params = ['id', 'materialId', 'num', 'price']  array 自定义参数
     * @param bool $isEdit
     * @param array $append
     * @return array
     */
    private static function createInvoiceRow(array $params = [], bool $isEdit = true, $append = [])
    {
        $material    = $params['material'] ?? query('material', " id = '$params[materialId]'");
        $params['list'] = $params['list'] ?? '';
        $operate     = componentClass::tablePperation($params['list'], "delTableRow(this);totalAmountInvoice()") .
            hidden(['name' => 'mxId[]', 'value' => $params['id']]) .
            hidden(['name' => 'price[]', 'value' => $params['price']]) .
            hidden(['name' => 'tax[]', 'value' => $params['tax']]) .
            hidden(['name' => 'sourceId[]', 'value' => $params['sourceId']]);
        $data = [
            $operate,
            $params['sale_orderNo'],
            $params['send_orderNo'],
            $material['code'],
            $material['name'],
            $params['send_num'],
            !$isEdit ? self::lostZero($params['num'], 'num') : text([
                'name' => 'num[]',
                'class' => 'text width150',
                'blur' => 'countInvoiceMoney',
                'data' => ['max' => $params['num'], 'min' => 0],
                'other' => self::digitalFiltering('num'),
                'value' => self::lostZero($params['num'], 'num')
            ]),
            self::lostZero($params['price'], 'price'),
            ($params['tax'] * 100).'%',
            "<span class='money'>".self::lostZero($params['money'])."</span>"
        ];
        // 非编辑移除第一列
        if (!$isEdit) {
            array_shift($data);
        }
        if (!self::is_null_array($append)) {
            $data = array_merge($data, $append);
        }
        return $data;
    }


    /**
     * 开票申请
     * @return bool|string
     */
    public function invoiceApply(): bool|string
    {
        $id   = $this->post('id') ?: self::getId();
        $info = query('invoice_open', " id = '" . $id . "' ");
        $isEdit = empty($info['id']);
        $title = [
            '',
            L('销售单号'),
            L('发货单号'),
            L('产品编码'),
            L('产品名称'),
            L('发货数量'),
            must . L('开票数量'),
            L('无税单价') . '(' . static::$unit . ')',
            L('税率') . '(%)',
            L('价税合计') . '（' . static::$unit . '）',
        ];
        // 非编辑移除第一列
        if (!$isEdit) {
            array_shift($title);
        }
        $tr[]     = $title;
        $result   = find(['table' => 'invoice_open_detail', 'where' => "orderId = '$info[id]' order by list"]);
        $totalArr = ['num' => 0, 'money' => 0];
        foreach ($result['array'] as $k => $array) {
            $array['list'] = $k + 1;
            $sale_send_order_detail = query("sale_send_order_detail", " id = '" . $array['sourceId'] . "' ");
            $array['material'] = query('material', " id = '$sale_send_order_detail[materialId]'");
            $array['materialId'] = $sale_send_order_detail['materialId'];
            $array['send_num'] = self::lostZero($sale_send_order_detail['num'], 'num');
            $sale_send_order = query("sale_send_order", " id = '" . $sale_send_order_detail['orderId'] . "' ");
            $sale_order = query("sale_order", " id = '" . $sale_send_order_detail['saleOrderId'] . "' ");
            $array['sale_orderNo'] = $sale_order['orderNo'];
            $array['send_orderNo'] = $sale_send_order['orderNo'];
            $array['price'] = $array['price'] / $array['baseUnit'];
            $tr[] = self::createInvoiceRow($array, $isEdit);
            $totalArr['num']             += $array['num'];
            $totalArr['money']           += $array['money'];
        }
        $total      = [
            6  => "<span id='total_num'>" . self::lostZero($totalArr['num'], 'num') . "</span>",
            9 => "<span id='total_money'>" . self::lostZero($totalArr['money']) . "</span>",
        ];
        $table      = $this->tableMany(['tr' => $tr, 'end' => true, 'total' => $total]);
        $mxButton   = !$isEdit ? '' : sprintf(<<<efo
                    <span class="smallButton" onclick="layer('%s','addSendOrder',$('form[name=invoiceApplyForm]').serialize())">%s</span>
efo,
            $this->get('cla'),
            L('选择发货单')
        );
        $kehu       = query('kehu', "khid = '$info[khid]'");
        //表单
        $body           = $this->edit4([
            L('基本信息') => [
                [
                    must . L('客户') . "："   =>
                        !$isEdit ? $kehu['companyName'] : componentClass::selectText([
                            'name'   => 'khid',
                            'value'  => $info['khid'],
                            'title'  => L('请选择客户'),
                            'text'  => $kehu['companyName'],
                            'cla'    => 'saleOrder',
                            'fun'    => 'getClient',
                            'change' => 'getkehuInfo',
                        ]),
                    L('纳税识别号') . "："          =>
                        "<div id='buyTaxNo' class='full'>" .
                        $info['buyTaxNo'] .
                        "</div>",
                ],
                [
                    L('地址、电话') . "："         =>
                        "<div id='buyAddress' class='full'>" .
                        $info['buyAddress'] .
                        "</div>",
                    L('开户行及账号') . "："         =>
                        "<div id='buyBank' class='full'>" .
                        $info['buyBank'] .
                        "</div>",
                ],
                [
                    L('备注') . "：" => !$isEdit ? $info['text'] : textarea(["name" => "text", 'class' => 'text', "value" => $info['text']]),
                ],
            ]
        ]);
        $body           .= $this->editList([
            'id'     => 'invoiceTable',
            'title'  => L('开票明细'),
            'button' => $mxButton,
            'html'   => $table,
        ]);
        $company = query("company", " coid = '".self::$coid."' ");
        $invoice_payee = $company['invoice_payee'] ?
            self::findStaff($company['invoice_payee']).hidden(['name' => 'invoice_payee', 'value' => $company['invoice_payee']]) :
            selectMultiple(["name" => "invoice_payee", 'where' => "state != '离职' and workFlow = '已复核'", 'table' => 'staff', 'sqlId' => 'stid', 'sqlField' => 'name', 'title' => '请选择', "value" => self::$stid]);
        $invoice_reviewer = $company['invoice_reviewer'] ?
            self::findStaff($company['invoice_reviewer']).hidden(['name' => 'invoice_reviewer', 'value' => $company['invoice_reviewer']]) :
            selectMultiple(["name" => "invoice_reviewer", 'where' => "state != '离职' and workFlow = '已复核'", 'table' => 'staff', 'sqlId' => 'stid', 'sqlField' => 'name', 'title' => '请选择', "value" => self::$stid]);
        $invoice_drawer = $company['invoice_drawer'] ?
            self::findStaff($company['invoice_drawer']).hidden(['name' => 'invoice_drawer', 'value' => $company['invoice_drawer']]) :
            selectMultiple(["name" => "invoice_drawer", 'where' => "state != '离职' and workFlow = '已复核'", 'table' => 'staff', 'sqlId' => 'stid', 'sqlField' => 'name', 'title' => '请选择', "value" => self::$stid]);
        $body           .= $this->edit4([
            [
                [
                    L('销售方') . "："         => $company['invoiceCompany'],
                    L('纳税人识别号') . "："         => $company['invoiceNo'],
                    L('地址、电话') . "："         => $company['addressAndTel'],
                    L('开户行及账号') . "："         => $company['bankName'],
                ],
                [
                    L('收款人') . "："         => $invoice_payee,
                    L('复核人') . "："         => $invoice_reviewer,
                    L('开票人') . "："         => $invoice_drawer,
                ],
            ]
        ]);
        $html = "<form name='invoiceApplyForm'>
                    ".$body.
            hidden(['name' => 'id', 'value' => $id])."
                </form>";
        $html .= <<<efo
<script>
//根据客户获取客户详情
function getkehuInfo(data){
    $("#buyTaxNo").html(data.companyNum ? data.companyNum : "<span class='red'>请先完善客户信息！</span>");
    $("#buyAddress").html(data.companyAddress ? data.companyAddress : "<span class='red'>请先完善客户信息！</span>");
    $("#buyBank").html(data.companyBank ? data.companyBank + data.companyBankNum : "<span class='red'>请先完善客户信息！</span>");
}
function addInvoiceRow(){
    $.post(root+'control/adIndex.html?cla={$this->get('cla')}&fun=addInvoiceRowEdit',$("form[name='saleSendOrderForm']").serialize(),function(res) {
        let tbody = $("#invoiceTable tbody")
        tbody.append(res.html);
        resetNumber(tbody)
        totalAmountInvoice()
        $('#saleInvoiceAddSendOrder').hide()
    },'json');
}
//计算金额
function countInvoiceMoney(e){
    let tr = $(e).closest('tr')
    let num = tr.find('[name="num[]"]').val(),
        price = tr.find('[name="price[]"]').val(),
        tax = tr.find('[name="tax[]"]').val()
    let money = Number(num) * Number(price) * (1 + Number(tax))
    tr.find(".money").html(fixPrecision(money, amountPrecision))
    totalAmountInvoice()
}
//计算总数量
function totalAmountInvoice(){
    let table = $('.editList')
    let num = 0,
    money = 0
    table.find("[name='num[]']").each(function(index){
        if($(this).val()){
          num+=Number($(this).val());
        }
        var moneyText = table.find(".money").eq(index).text()
        if(moneyText){
            money+=Number(moneyText);
        }
    })
    $("#total_num").text(num.toFixed(publicSettings.numPrecision.num));
    $("#total_money").text(money.toFixed(amountPrecision));
}
</script>

efo;
        $url     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=" . $this->get('fun') . "Edit";
        $button = !$isEdit ? false : "<input onclick=\"subForm('invoiceApplyForm','" . $url . "')\" type='button' class='button' value='" . L('确认提交') . "'>";
        return $this->layer(array("title" => L('销项发票申请'), "height" => 600, "width" => 1200, "html" => $html, "button" => $button));
    }

    /**
     * 编辑
     */
    public function invoiceApplyEdit()
    {
        $id = $this->post('id') ?: self::getId();
        $mxIdArr = $this->post('mxId') ?: [];
        $sourceIdArr = $this->post('sourceId');
        $numArr = $this->post('num');
        $kehu        = query("kehu", " khid = '" . $this->post('khid') . "' ");
        //带出账套的发票信息
        $company    = query('company', "coid = '" . self::$coid . "'");
        $field      = [
            'buyCompany'  => $kehu['invoiceCompany'],
            'buyTaxNo'    => $kehu['companyNum'],
            'buyAddress'  => $kehu['companyAddress'],
            'buyBank'     => $kehu['companyBank'] . $kehu['companyBankNum'],
            'khid'        => $this->post('khid'),
            'saleCompany' => $company['invoiceCompany'],
            'saleTaxNo'   => $company['invoiceNo'],
            'saleAddress' => $company['addressAndTel'],
            'saleBank'    => $company['bankName'],
            'receive_stid'    => $this->post('invoice_payee'),
            'receiveName'    => self::findStaff($this->post('invoice_payee')),
            'check_stid'    => $this->post('invoice_reviewer'),
            'checkName'    => self::findStaff($this->post('invoice_reviewer')),
            'create_stid'    => $this->post('invoice_drawer'),
            'createName'    => self::findStaff($this->post('invoice_drawer')),
            'text'        => $this->post('text'),
        ];
        $annotation = [
            'buyCompany'  => L('请完善客户的开票信息【公司名称】'),
            'buyTaxNo'    => L('请完善客户的开票信息【纳税人识别号】'),
            'saleCompany' => L('请完善销售方信息【销货单位】'),
            'saleTaxNo'   => L('请完善销售方信息【纳税人识别号】'),
            'receive_stid'   => L('收款人'),
            'check_stid'   => L('复核人'),
            'create_stid'   => L('开票人'),
        ];
        $rules      = [
            'buyCompany'  => 'required',
            'buyTaxNo'    => 'required',
            'saleCompany' => 'required',
            'saleTaxNo'   => 'required',
        ];

        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if ($result === false) {
            $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
            goto resp;
        }
        $where = " id = '$id' ";
        $info  = query('invoice_open', $where);
        //判断
        if (static::is_null_array($mxIdArr)) {
            $json['warn'] = L('请填写开票明细');
        } else {
            $this->startTrans();
            if (!$info['id']) {
                $field        = array_merge($field, [
                    'id'    => $id,
                    'coid'  => self::$coid,
                    'type'  => '开票',
                    'source'  => 1,
                    'stid'        => self::$stid,
                ]);
                $json['warn'] = static::insert(["table" => 'invoice_open', "field" => $field]);
            } else {
                $json['warn'] = static::update([
                    "table" => 'invoice_open',
                    "field" => $field,
                    "where" => $where,
                ]);
            }
            //选项设置
            $totalMoney = $taxTotalMoney = 0;
            $priceDecimal = openInvoiceClass::priceDecimal();
            $ids        = [];
            foreach ($mxIdArr as $k => $mxId) {
                $detail     = query('invoice_open_detail', "id = '$mxId'");
                $ids[]      = $mxId;
                if (empty($numArr[$k]) || !is_numeric($numArr[$k])) {
                    $json['warn'] = str_replace(['{{x}}'], [$k + 1], L('请填写第{{x}}行开票数量'));
                    break;
                }elseif (empty($sourceIdArr[$k])) {
                    $json['warn'] = str_replace(['{{x}}'], [$k + 1], L('第{{x}}行未关联源单'));
                    break;
                }
                $sale_send_order_detail = query("sale_send_order_detail"," id = '$sourceIdArr[$k]' ");
                $material = query('material', " id = '$sale_send_order_detail[materialId]'");
                $price_no_tax = self::formattingFigure($sale_send_order_detail['price']/(1+$sale_send_order_detail['rate']), 'price');
                $baseUnit = currencyClass::calculateDecimal($price_no_tax);
                $moeny = self::formattingFigure($numArr[$k] * $price_no_tax * (1 + $sale_send_order_detail['rate']));
                $taxMoney               = self::formattingFigure($numArr[$k] * $price_no_tax * $sale_send_order_detail['rate']);
                $mxField = [
                    'name'        => $material['name'],
                    'model'       => $material['model'],
                    'unit'        => $sale_send_order_detail['unit'],
                    'price'       => $price_no_tax * $baseUnit,
                    'baseUnit'    => $baseUnit,
                    'num'         => $numArr[$k],
                    'money'       => $moeny,
                    'tax'         => $sale_send_order_detail['rate'],
                    'taxMoney'    => $taxMoney,
                    'sourceId'    => $sourceIdArr[$k],
                    'sourceTable' => 'sale_send_order_detail'
                ];
                if (empty($detail['id'])) {
                    $invoice_num = (float)$sale_send_order_detail['invoice_num'] + $numArr[$k];
                    $warn           = static::insert(array(
                        'table' => 'invoice_open_detail',
                        'field' => array_merge([
                            'id'          => $mxId,
                            'coid'        => self::$coid,
                            'orderId'     => $id,
                        ], $mxField)
                    ));
                } else {
                    $invoice_num        = (float)$sale_send_order_detail['invoice_num'] - $detail['num'] + $numArr[$k];
                    $warn                  = static::update(array(
                        'table' => 'invoice_open_detail',
                        'field' => $mxField,
                        'where' => "id = '$detail[id]'"
                    ));
                }
                $taxTotalMoney += $taxMoney;
                $totalMoney    += $moeny;
                if (!in_array($warn, ["新增成功", "更新成功"])) {
                    $json['warn'] = $warn;
                    break;
                }
                // 更新销售发货单已开票金额
                if ($sale_send_order_detail['id']) {
                    update(array(
                        'table' => "sale_send_order_detail",
                        'field' => [
                            'invoice_num' => $invoice_num,
                        ],
                        'where' => "id = '" . $sale_send_order_detail['id'] . "'"
                    ));
                }
            }
            $warn = update(array(
                'table' => 'invoice_open',
                'field' => [
                    'money' => $totalMoney,
                    'unTaxMoney' => $totalMoney - $taxTotalMoney,
                    'taxMoney' => $taxTotalMoney
                ],
                'where' => "id = '$id'"));
            if ($warn != '更新成功') {
                $json['warn'] = $warn;
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                $this->commitTrans();
                delete(array('table' => 'invoice_open_detail', "where" => "id not in ('" . implode("','", $ids) . "') and orderId = '$id'"));
                //添加日志
                $text = str_replace(['{{staffName}}', '{{id}}'], [$this->control['name'], $id], L('{{staffName}}提交了销项发票申请，ID【{{id}}】'));
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
            } else {
                $this->rollback();
            }
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 关联销售发货单
     * @return bool|string
     */
    public function addSendOrder(): bool|string
    {
        if(empty($this->post('khid'))){
            return json_encode(['warn' => '请先选择客户']);
        }
        $html   =
            text(array("name" => "saleOrderNo", "title" => L('销售单号'))) .
            text(array("name" => "orderNo", "title" => L('销售发货单号'))) .
            text(array("name" => "recordDate", 'class' => 'width200', 'laydate' => ['type' => 'date', 'range' => '~'], "title" => L('发货单据日期'))).
            hidden(array("name" => "khid", "value" => $this->post('khid'))).
            hidden(array('name' => 'sourceId', 'value' => $this->post('sourceId') ? implode(',', $this->post('sourceId')) : ''));
        $button = "<input onclick=\"addInvoiceRow()\" type='button' class='button' value='" . L('确认提交') . "'>";
        $html   = $this->search($html);
        return $this->layer(array("title" => L('添加'), "zindex" => 5, "height" => 600, "width" => 1200, "html" => $html, "button" => $button));
    }

    /**
     * 关联销售发货单
     * @return bool|string
     */
    public function addSendOrderSearch(): bool|string
    {
        $sourceId = $this->post('sourceId') ? explode(',', $this->post('sourceId')) : [];
        $where = "ord.khid = '" . $this->post('khid') . "' and detail.id not in ('" . implode("','", $sourceId) . "')";
        $like  = [
            'ord.orderNo' => $this->post('orderNo'),
        ];
        $equal = [
            'ord.state' => '已确认',
            'ord.coid'  => self::$coid,
        ];
        if ($this->post('recordDate')) {
            //单据日期
            $where .= self::timeComparison($this->post('recordDate'), 'date', 'recordDate');
        }
        if ($this->post('saleOrderNo')) {
            //单据日期
            $where .= " and detail.saleOrderId <> '' and detail.saleOrderId in (select id from sale_order where orderNo like '%" . $this->post('saleOrderNo') . "%' and coid = '" . self::$coid . "') ";
        }
        $where .= " and (detail.num - detail.invoice_num) > 0 ";  // 未完成开票的
        $where .= search(["like" => $like, "=" => $equal]);
        $page  = $this->page([
            "table"   => "sale_send_order_detail as detail join sale_send_order as ord on detail.orderId = ord.id",
            "field"   => "detail.*,ord.recordDate,ord.khid,ord.orderNo,(detail.num - detail.invoice_num) as residue",
            "where"   => $where,
            'pageNum' => 50,
            "order"   => "detail.`time` desc",
        ]);
        //获取表头
        $checkAll = $this->checkAll("saleSendOrderForm", "detailId");
        $tr[]     = [
            $checkAll,
            L('销售单号'),
            L('发货单号'),
            L('单据日期'),
            L('产品编码'),
            L('产品名称'),
            L('无税单价') . '(' . self::$unit . ')',
            L('税率') . '(%)',
            L('价税合计') . '(' . self::$unit . ')',
            L('剩余未开票数量')
        ];
        //获取记录
        foreach ($page['array'] as $array) {
            $dominate   = array(
                "box" => array("name" => "detailId", "value" => $array['id']),
            );
            $sale_order = query("sale_order", " id = '" . $array['saleOrderId'] . "' ");
            $material   = query("material", " id = '" . $array['materialId'] . "' ");
            $price_no_tax = self::formattingFigure($array['price']/(1+$array['rate']), 'price');
            $tr[] = array(
                $this->dominate($dominate),
                $sale_order['orderNo'],
                $array['orderNo'],
                $array['recordDate'],
                $material['code'],
                $material['name'],
                $price_no_tax,
                ($array['rate'] * 100).'%',
                self::lostZero($array['money']),
                self::lostZero($array['residue'], 'num'),
            );
        }
        $json['html'] = $page['hint'] .
            "<form name='saleSendOrderForm'>" .
            hidden(array('name' => 'khid', 'value' => $this->post('khid'))) .
            $this->tableMany(array("tr" => $tr, "showSort" => true, "page" => $page['para'])) .
            "</form>" .
            $page['button'];
        return json_encode($json, 320);
    }

    /**
     * 编辑
     *
     * @return bool|string
     */
    public function addInvoiceRowEdit()
    {
        $mxIdArr = $this->post('detailId');
        if (empty($mxIdArr) || !is_array($mxIdArr)) {
            $json['warn'] = L('请选择数据');
        } else {
            $tr = [];
            foreach ($mxIdArr as $mxId) {
                $sale_send_order_detail = query("sale_send_order_detail", " id = '" . $mxId . "' ");
                $material = query('material', " id = '$sale_send_order_detail[materialId]'");
                $sale_send_order = query("sale_send_order", " id = '" . $sale_send_order_detail['orderId'] . "' ");
                $sale_order = query("sale_order", " id = '" . $sale_send_order_detail['saleOrderId'] . "' ");
                $residue = self::formattingFigure($sale_send_order_detail['num'] - $sale_send_order_detail['invoice_num'], 'num');
                $price_no_tax = self::formattingFigure($sale_send_order_detail['price']/(1+$sale_send_order_detail['rate']), 'price');
                $tr[] = self::createInvoiceRow([
                    'id' => self::getId(),
                    'material' => $material,
                    'materialId' => $material['id'],
                    'price' => $price_no_tax,
                    'tax' => $sale_send_order_detail['rate'],
                    'sourceId' => $mxId,
                    'sale_orderNo' => $sale_order['orderNo'],
                    'send_orderNo' => $sale_send_order['orderNo'],
                    'send_num' => self::lostZero($sale_send_order_detail['num'], 'num'),
                    'num' => $residue,
                    'money' => self::formattingFigure($residue * $sale_send_order_detail['price']),
                ]);
            }
            $json['html'] = $this->tableMany(array('tr' => $tr, 'thead' => false));
            $json['warn'] = 2;
        }
        return json_encode($json, 320);
    }

    /*列表页-查询条件*/
    public function businessInvoiceOptions($isAsync = true)
    {
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    L('状态') => checkbox(array('name' => 'state', 'maintain_index' => true, 'value' => $this->stateOption, 'checked' => [0,1,2])),
                ],
                [
                    L('申请人')  => staffProfilesClass::staffSelectAsyn(array('title' => '')),
                    L('客户名称') => text(array("name" => "buyCompany")),
                    L('发票代码')   => text(array("name" => "invoiceCode")),
                ],
                [
                    L('发票号码') => text(array("name" => "invoiceNo")),
                    L('开票日期') => text(array("name" => "createTime", 'laydate' => ['type' => 'date', 'range' => '~'])),
                    L('备注') => text(array("name" => "text")),
                ],
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }


    /*列表-查询条件*/
    public function businessInvoice()
    {
        $html = $this->businessInvoiceOptions(false);
        //控件
        $button = "";
        if ($this->power('saleInvoiceApply', "edit")) {
            $button .= "<span class='spanButton' onclick=\"layer('saleInvoice','invoiceApply')\">" . L('开票申请') . "</span>";
        }
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /*客户列表-查询结果*/
    public function businessInvoiceSearch()
    {
        //like查询数组
        $like = array(
            //编号
            "text" => $this->post('text'),//事由
            "buyCompany" => $this->post('buyCompany'),
            "saleCompany" => $this->post('saleCompany'),
            "invoiceNo" => $this->post('invoiceNo'),
            "invoiceCode" => $this->post('invoiceCode'),
        );
        //全等查询数组
        $equal = array(
            "stid" => $this->post('stid'),
            "classify" => $this->post('invoiceType'),
            "type" => '开票',
            "source" => 1,
            'coid' => self::$coid
        );
        //in查询数组
        $in = array(
            "state" => $this->post('state'),
        );
        $and = '';
        if ($this->post('createTime')) {
            $and.=self::timeComparison($this->post('createTime'),field: 'invoiceDate');
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'time',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        //获取查询结果
        $where = search(array("like" => $like, "=" => $equal, "in" => $in)) . $and;
        $page = $this->page(array("table" => self::table, "where" => $where, "order" => $orderBy['orderBy']));
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        //获取记录
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = array(
                "box" => array("name" => "listId", "value" => $array['id']),
                "detail" => array("title" => L('销项发票详情'), "click" => "layer('saleInvoice','invoiceApply',{id:'" . $array['id'] . "'})"),
            );
            $liButton[] = $this->dominate($dominate);
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    case 'stid':
                        $row[] = self::findStaff($array['stid']);
                        break;
                    case 'state':
                        $row[] = $array['state'] == 2 ? "<span class='red'>".$this->stateOption[$array['state']]."</span>" : $this->stateOption[$array['state']];
                        break;
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = $page['hint'] . "<form name='listForm'>" . $li . "</form>" . $page['button'] . clear;
        return json_encode($json, 320);
    }

    /**
     * 发票填开
     * @return bool|string
     */
    public function invoicing(): bool|string
    {
        $id   = $this->post('id');
        $type   = $this->post('type');
        $info = query('invoice_open', " id = '" . $id . "' ");
        if(empty($info['id'])){
            return json_encode(['warn' => L('对象为空'), 320]);
        }
        if(empty($type)){
            return json_encode(['warn' => L('操作类型为空'), 320]);
        }
        $tr[]     = [
            L('货物或应税劳务、服务名称'),
            L('规格型号'),
            L('单位'),
            L('数量'),
            L('单价'),
            L('金额'),
            L('税率') . '(%)',
            L('税额'),
        ];
        $result   = find(['table' => 'invoice_open_detail', 'where' => "orderId = '$info[id]' order by list"]);
        $totalArr = ['moneyWithOutTax' => 0, 'taxMoney' => 0];
        foreach ($result['array'] as $k => $array) {
            $moneyWithOutTax = $array['money'] - $array['taxMoney'];
            $tr[] = [
                $array['name'],
                $array['model'],
                $array['unit'],
                $array['num'],
                $array['price']/$array['baseUnit'],
                $moneyWithOutTax,
                ($array['tax']*100).'%',
                $array['taxMoney'],
            ];
            $totalArr['moneyWithOutTax']           += $moneyWithOutTax;
            $totalArr['taxMoney']           += $array['taxMoney'];

        }
        $total_money = $totalArr['moneyWithOutTax'] + $totalArr['taxMoney'];
        $customize_tr = "<tfoot>
                            <tr>
                                <td></td>
                                <td>合计</td>
                                <td></td>
                                <td></td>
                                <td></td>
                                <td></td>
                                <td>" . self::lostZero($totalArr['moneyWithOutTax']) . "</td>
                                <td></td>
                                <td>" . self::lostZero($totalArr['taxMoney']) . "</td>
                            </tr>
                            <tr>
                                <td></td>
                                <td>价税合计(大写)</td>
                                <td colspan='7'>
                                    <div style='display: flex;justify-content: space-between;padding: 0 10px;'>
                                        <div>".voucherEditClass::num_to_rmb($total_money)."</div>
                                        <div>(小写)：".$total_money."</div>
                                    </div>
                                </td>
                            </tr>
                        </tfoot>";
        $table      = $this->tableMany(['tr' => $tr, 'end' => true, 'showSort' => true, 'customize_tr' => $customize_tr]);
        // 发票填开
        if($type == 'fill'){
            $operate = [
                [
                    must.L('发票代码') . "：" => text(array("name" => "invoiceCode", "title" => L('请填写'))),
                    must.L('开票日期') . "：" => text(array("name" => "invoiceDate", 'laydate' => [], "title" => L('请填写'))),
                    must.L('发票号') . "：" => text(array("name" => "invoiceNo", "title" => L('请填写'))),
                ]
            ];
            // 发票冲红
        }elseif($type == 'red'){
            $operate = [
                [
                    must.L('冲红发票代码') . "：" => text(array("name" => "invoiceCode", "title" => L('请填写'))),
                    must.L('冲红日期') . "：" => text(array("name" => "invoiceDate", 'laydate' => [], "title" => L('请填写'))),
                    must.L('冲红发票号') . "：" => text(array("name" => "invoiceNo", "title" => L('请填写'))),
                ],
                [
                    L('冲红备注') . "：" => textarea(["name" => "text", 'class' => 'text', "title" => L('请填写')]),
                ],
            ];
            // 查看发票
        }else{
            $operate = [
                [
                    L('发票代码') . "：" => $info['invoiceCode'],
                    L('开票日期') . "：" => $info['invoiceDate'],
                    L('发票号') . "：" => $info['invoiceNo'],
                ]
            ];
        }
        //表单
        $body           = $this->edit4([
            L('基本信息') => array_merge($operate,
                [
                    [
                        L('购买方') . "："   => $info['buyCompany'],
                        L('纳税人识别号') . "："   => $info['buyTaxNo'],
                        L('地址、电话') . "："   => $info['buyAddress'],
                    ],
                    [
                        L('开户行及账号') . "："   => $info['buyBank'],
                        L('备注') . "：" => $info['text'],
                    ],
                ])
        ]);
        $body           .= $this->editList([
            'id'     => 'invoiceTable',
            'title'  => L('开票明细'),
            'html'   => $table,
        ]);
        $body           .= $this->edit4([
            [
                [
                    L('销售方') . "："         => $info['saleCompany'],
                    L('纳税人识别号') . "："         => $info['saleTaxNo'],
                    L('地址、电话') . "："         => $info['saleAddress'],
                    L('开户行及账号') . "："         => $info['saleBank'],
                ],
                [
                    L('收款人') . "："         => $info['receiveName'],
                    L('复核人') . "："         => $info['checkName'],
                    L('开票人') . "："         => $info['createName'],
                ],
            ]
        ]);
        $html = "<form name='invoicingForm'>
                    ".$body.
            hidden(['name' => 'id', 'value' => $id]).
            hidden(['name' => 'type', 'value' => $type]).
            "</form>";
        $url     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=" . $this->get('fun') . "Edit";
        $button = $type == 'see' ? false : "<input onclick=\"subForm('invoicingForm','" . $url . "')\" type='button' class='button' value='" . L('确认提交') . "'>";
        return $this->layer(array("title" => L('销项发票填开'), "height" => 600, "width" => 1200, "html" => $html, "button" => $button));
    }

    /**
     * 编辑
     */
    public function invoicingEdit()
    {
        $id = $this->post('id');
        $type = $this->post('type');
        $json = [];
        if($type == 'fill') {
            $field      = [
                'invoiceCode' => $this->post('invoiceCode'),
                'invoiceDate' => $this->post('invoiceDate'),
                'invoiceNo'   => $this->post('invoiceNo'),
                'state'       => 1,
            ];
            $annotation = [
                'invoiceCode' => L('发票代码'),
                'invoiceDate' => L('开票日期'),
                'invoiceNo'   => L('发票号'),
            ];
            $rules      = [
                'invoiceCode' => 'required',
                'invoiceDate' => 'required',
                'invoiceNo'   => 'required',
            ];

            // 校验是否符合规则
            $vt     = new \verify();
            $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
            if ($result === false) {
                $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
                goto resp;
            }
            $where = " id = '$id' ";
            $info  = query('invoice_open', $where);
            //判断
            if (empty($info['id'])) {
                $json['warn'] = L('填开对象为空');
            } else {
                $this->startTrans();
                $json['warn'] = static::update([
                    "table" => 'invoice_open',
                    "field" => $field,
                    "where" => $where,
                ]);
                if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                    $this->commitTrans();
                    //添加日志
                    $text = str_replace(['{{staffName}}', '{{id}}'], [$this->control['name'], $id], L('{{staffName}}操作了销项发票填开，ID【{{id}}】'));
                    $this->logText(["type" => self::page, "text" => $text]);
                    //返回
                    $_SESSION['warn'] = L('提交成功');
                    $json['warn']     = 2;
                } else {
                    $this->rollback();
                }
            }
        }elseif($type == 'red'){
            $field      = [
                'invoiceCode' => $this->post('invoiceCode'),
                'invoiceDate' => $this->post('invoiceDate'),
                'invoiceNo'   => $this->post('invoiceNo'),
                'text'   => $this->post('text'),
            ];
            $annotation = [
                'invoiceCode' => L('冲红发票代码'),
                'invoiceDate' => L('冲红日期'),
                'invoiceNo'   => L('冲红发票号'),
            ];
            $rules      = [
                'invoiceCode' => 'required',
                'invoiceDate' => 'required',
                'invoiceNo'   => 'required',
            ];

            // 校验是否符合规则
            $vt     = new \verify();
            $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
            if ($result === false) {
                $json['warn'] = $vt->getErrs()[0];  // 多个规则提示最前面一条
                goto resp;
            }
            $where = " id = '$id' ";
            $info  = query('invoice_open', $where);
            if (empty($info['id'])) {
                $json['warn'] = L('冲红对象为空');
            } else {
                $this->startTrans();
                // 插入新的冲红发票
                $field = array_merge($info, $field);
                $field['id'] = self::getId();
                $field['state'] = 2;
                $field['taxMoney'] = -$field['taxMoney'];
                $field['unTaxMoney'] = -$field['unTaxMoney'];
                $field['money'] = -$field['money'];
                $field['red_target'] = $id;
                $field['stid'] = self::$stid;
                $field['updateTime'] = $this->time;
                $field['time'] = $this->time;
                $json['warn'] = static::insert(["table" => 'invoice_open', "field" => $field]);
                if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                    // 插入冲红明细
                    $result   = find(['table' => 'invoice_open_detail', 'where' => "orderId = '$info[id]' order by list"]);
                    foreach ($result['array'] as $k => $array) {
                        $array['id'] = self::getId();
                        $array['orderId'] = $field['id'];
                        static::insert(array(
                            'table' => 'invoice_open_detail',
                            'field' => $array
                        ));
                        // 更新销售发货单已开票数量
                        $sale_send_order_detail = query("sale_send_order_detail"," id = '$array[sourceId]' ");
                        if($sale_send_order_detail['id']){
                            update(array(
                                'table' => "sale_send_order_detail",
                                'field' => [
                                    'invoice_num' => $sale_send_order_detail['invoice_num'] - $array['num'],
                                ],
                                'where' => "id = '" . $sale_send_order_detail['id'] . "'"
                            ));
                        }
                    }
                    $this->commitTrans();
                    //添加日志
                    $text = str_replace(['{{staffName}}', '{{id}}'], [$this->control['name'], $id], L('{{staffName}}操作了销项发票冲红，ID【{{id}}】'));
                    $this->logText(["type" => self::page, "text" => $text]);
                    //返回
                    $_SESSION['warn'] = L('提交成功');
                    $json['warn']     = 2;
                } else {
                    $this->rollback();
                }
            }
        }

        resp:
        return json_encode($json, 320);
    }
}
